package edu.gdin.ecommerce.service.impl;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import jxl.Workbook;
import jxl.write.WritableWorkbook;

import org.springframework.stereotype.Service;

import edu.gdin.ecommerce.dao.CardBatchDAO;
import edu.gdin.ecommerce.dao.CardIssuerDAO;
import edu.gdin.ecommerce.dao.InventoryDAO;
import edu.gdin.ecommerce.model.CardBatch;
import edu.gdin.ecommerce.model.CardIssuer;
import edu.gdin.ecommerce.model.Inventory;
import edu.gdin.ecommerce.model.OperLog;
import edu.gdin.ecommerce.model.User;
import edu.gdin.ecommerce.service.ICardBatchService;
import edu.gdin.ecommerce.service.exception.ServiceException;
import edu.gdin.ecommerce.util.DateUtil;
import edu.gdin.ecommerce.util.ExportExcel;
import edu.gdin.ecommerce.util.FilePath;
import edu.gdin.ecommerce.util.GenerateRandom;
import edu.gdin.ecommerce.util.Pager;
import edu.gdin.ecommerce.util.ParamConverter;

@Service("cardBatchService")
public class CardBatchService implements ICardBatchService {

	private CardBatchDAO cardBatchDAO;
	private CardIssuerDAO cardIssuerDAO;
	private InventoryDAO inventoryDAO;

	public CardBatchDAO getCardBatchDAO() {
		return cardBatchDAO;
	}
	@Resource
	public void setCardBatchDAO(CardBatchDAO cardBatchDAO) {
		this.cardBatchDAO = cardBatchDAO;
	}
	public CardIssuerDAO getCardIssuerDAO() {
		return cardIssuerDAO;
	}
	@Resource
	public void setCardIssuerDAO(CardIssuerDAO cardIssuerDAO) {
		this.cardIssuerDAO = cardIssuerDAO;
	}
	public InventoryDAO getInventoryDAO() {
		return inventoryDAO;
	}
	@Resource
	public void setInventoryDAO(InventoryDAO inventoryDAO) {
		this.inventoryDAO = inventoryDAO;
	}
	
	
	/**
	 * 生成库存卡
	 * @param batch
	 * @param user
	 * @param faceValue
	 */
	public void makeCardByBatch(CardBatch batch, User user, BigDecimal faceValue) {
		if(batch.getNum() == null || batch.getNum() == 0) {
			throw new ServiceException("", "制卡 数目不能为0!");
		}
		if(batch.getSectionBegin() == null || batch.getSectionEnd() == null) {
			batch.setSectionBegin("");
			batch.setSectionEnd("");
		}
		// 卡号数字验证
		if(batch.getSectionBegin().trim().length() != batch.getSectionEnd().trim().length()) {
			throw new ServiceException("", "起始号段和结束号段长度不等!");
		}
		
		CardIssuer issuer = (CardIssuer) this.cardIssuerDAO.findByPk(CardIssuer.class, batch.getCardIssuer().getCardIssuerId());
		String tempBegin = issuer.getCardFlag() + batch.getSectionBegin().trim();
		String tempEnd = issuer.getCardFlag() + batch.getSectionEnd().trim();
		
		if(tempBegin.compareTo(tempEnd) > 0) {
			throw new ServiceException("", "起始号段不能大于结束号段!");
		}
		
		int cardLength = 16;
		int diffLength = cardLength - tempBegin.length();
		if(diffLength < 0) {
			throw new ServiceException("", "卡号长度超过" + cardLength + "位");
		}
		
		String temp1 = "";
		String temp2 = "";
		for(int i=0; i<diffLength-1; i++) { // ?????????
			temp1 += "0";
			temp2 += "9";
		}
		String cardNoBegin = tempBegin + temp1;
		String cardNoEnd = tempEnd + temp2;
		if(Long.parseLong(cardNoEnd) - Long.parseLong(cardNoBegin) < batch.getNum()) {
			throw new ServiceException("", "起始号段和结束号段之间隔过小，不足生成足够数量卡号!");
		}
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		Date now = DateUtil.now();
		batch.setBatchNo(sdf.format(now));
		batch.setStatus(1); // 1=卡号生成
		batch.setApplicant(user.getAccount());
		batch.setSectionBegin(cardNoBegin); //起始卡号段更新为起始卡号
		batch.setSectionEnd(cardNoEnd);
		batch.setCreateTime(now);
		this.cardBatchDAO.insert(batch);
		
		//List<String> cardNos = new ArrayList<String>();
		for(int i = 0; i < batch.getNum(); i++) {
			String cardNo = cardNoBegin;
			String cardNoCheck = "";
			boolean flag = false;
			for(int j = 0; j < 100; j++) {
				cardNoCheck = cardNo + GenerateRandom.getBankCardCheckCode(cardNo);
				Inventory in = (Inventory) this.inventoryDAO.findByPk(Inventory.class, cardNoCheck);
				if(in != null) {
					long diff = Long.parseLong(cardNoEnd) - Long.parseLong(cardNo);
					if (diff > (batch.getNum() - i) * 10) {
						cardNo = String.valueOf(Long.parseLong(cardNo) + (long) (Math.random() * diff));
					} else {
						cardNo = String.valueOf(Long.parseLong(cardNo) + 1);
					}
					
					if(Long.parseLong(cardNo) > Long.parseLong(cardNoEnd)) {
						throw new ServiceException("", "起始号段和结束号段之间隔过小，不足生成足够数量卡号!");
					}
					
					continue;
				} else {
					flag = true;
					break;
				}
			}
			if(flag == false) {
				throw new ServiceException("", "起始号段和结束号段之间隔过小，不足生成足够数量卡号!");
			}
			
			Inventory inventory = new Inventory();
			inventory.setInventoryNo(cardNoCheck);
			inventory.setPassword(GenerateRandom.randomStringNum(6));
			inventory.setBatchNo(batch.getBatchNo());
			inventory.setStatus(1); // 1=卡号生成
			inventory.setApplicant(user.getAccount());
			inventory.setMaterialType(batch.getMaterialType());
			inventory.setFaceValue(faceValue);
			
			String temp = GenerateRandom.randomStringNum(6);
			String tracks1 = "%B" + cardNoCheck + "^NM^0000520" + temp + "?";
			String tracks2 = ";" + cardNoCheck + "=0000520" + temp + "?";
			inventory.setTracks1(tracks1);
			inventory.setTracks2(tracks2);
			inventory.setCreateTime(now);
			inventory.setInventoryDesc(batch.getBatchDesc());
			inventory.setCardIssuer(issuer);
			this.inventoryDAO.insert(inventory);
		}
		
	}
	
	/**
	 * 根据条件查询CardBatch
	 * @param batch
	 * @param operTime1
	 * @param operTime2
	 * @param currentPage
	 * @return
	 */
	public Pager queryBatch(CardBatch batch, String operTime1, String operTime2, int currentPage) {
		Pager pager = this.cardBatchDAO.queryBatch(batch, operTime1, operTime2, currentPage);
		return pager;
	}
	
	/**
	 * 根据batchNo获取CardBatch
	 * @param batchNo
	 * @return
	 */
	public CardBatch getByBatchNo(String batchNo) {
		return (CardBatch) this.cardBatchDAO.findByPk(CardBatch.class, batchNo);
	}
	
	/**
	 * 若该批次卡状态为1，export之前改为2  // 1=卡号生成  2=卡文件生成
	 * @param batchNo
	 */
	public void exportStatus(String batchNo) {
		CardBatch exportBatch = (CardBatch) this.cardBatchDAO.findByPk(CardBatch.class, batchNo);
		if(exportBatch == null) {
			throw new ServiceException("", "导出错误：不存在该卡批次");
		}
		if(exportBatch.getStatus() == 1) {
			exportBatch.setStatus(2);
			this.cardBatchDAO.update(exportBatch);
			this.inventoryDAO.changeStatus(batchNo, 2);
		}
	}
	
	/**
	 * 根据batchNo导出Inventory
	 * @param batchNo
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public String exportByBatchNo(String batchNo) {
		CardBatch batch = (CardBatch) this.cardBatchDAO.findByPk(CardBatch.class, batchNo);
		List<Inventory> inventories = (List<Inventory>) this.inventoryDAO.getEntitysByKey(Inventory.class, "batchNo", batch.getBatchNo());
		
		String sheetTitle = "卡批次信息_" + batch.getCardIssuer().getName() + batch.getBatchNo();
		String fileName = sheetTitle + ".xls";
//		String downPath = FilePath.rootPath() + "admin/downloads/";
		String downPath = FilePath.downloadPath();
		
		File file1 = new File(downPath);
		if(!file1.isDirectory()) {
			file1.mkdir();
		}
		
		File file2 = new File(downPath + fileName);
		if(file2.exists()) {
			file2.delete();
		}
		
		// 声明Excel文件
		WritableWorkbook workBook;
		try {
			file2.createNewFile();
			workBook = Workbook.createWorkbook(file2);
			ExportExcel.inventoryByBatchNo(workBook, inventories, sheetTitle);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return FilePath.relativePath() + fileName;
	}
	
	/**
	 * 根据batchNo制卡  // 2=卡文件生成  3=已制卡
	 * @param batchNo
	 */
	public void makeCardStatus(String batchNo) {
		CardBatch batch = (CardBatch) this.cardBatchDAO.findByPk(CardBatch.class, batchNo);
		if(batch == null) {
			throw new ServiceException("", "制卡错误：不存在该卡批次");
		}
		if(batch.getStatus() == 2) {
			batch.setStatus(3);
			this.cardBatchDAO.update(batch);
			this.inventoryDAO.changeStatus(batchNo, 3);
		}
	}
	
	
}
